home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: MegaDisc / MegaDisc 43 (1995-03)(MegaDisc Digital Publishing)(AU)(Disk 2 of 2)[m bamcopy].zip / MegaDisc 43 (1995-03)(MegaDisc Digital Publishing)(AU)(Disk 2 of 2)[m bamcopy].adf / Programming / Pascal_Tutes / Tute12.pas < prev    next >
Pascal/Delphi Source File  |  1995-01-27  |  11KB  |  304 lines

  1. {
  2.  
  3.              «»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»
  4.              «»                                                  «» 
  5.              «»                 TUTORIAL TWELVE                  «» 
  6.              «»                                                  «» 
  7.              «»                        by                        «» 
  8.              «»                                                  «» 
  9.              «»                   Anthony Peck                   «» 
  10.              «»                                                  «» 
  11.              «»                                                  «» 
  12.              «»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«» 
  13.                                                                     
  14.  
  15.  
  16.          43  !¡  43  !¡  43  !¡  43  !¡  43  !¡  43  !¡  43  !¡  43
  17.  
  18.  
  19.          How many programmers does it take to change a global variable?
  20.  
  21.      Time to 'fess up.  That last tutorial was a bit of a dud.  The reason?
  22.      We defined the variables at the start of the program, and then the 
  23.      individual procedures had full access to all of them.  For instance, 
  24.      the procedure Getnumbers could change the variables Number and Result.  
  25.      This is called a "side-effect" in programming, and it means that bug 
  26.      hunting can be awfully difficult if each procedure can alter the 
  27.      variables.
  28.  
  29.      These "global" variables (defined at the outset of the program) should
  30.      be passed to the procedures, rather than letting the procedures just 
  31.      snatch and grab by themselves.  This way, we can control what 
  32.      variables each procedure can alter.
  33.  
  34.      For instance, let's take a program that takes a number from the user 
  35.      and determines if it is even or odd.  This will be such a world 
  36.      shattering project it's likely we'll all end up with Nobel Prizes...  
  37.  
  38.      Forward ------------------> }
  39.  
  40.     Program MDTute12 (Input,Output);
  41.  
  42.     {    This program will determine if a user entered
  43.  
  44.         number is even or odd!
  45.  
  46.                 Author : A N Peck
  47.  
  48.                 Date : 26 October 1994
  49.                 
  50.     Procedures used:
  51.  
  52.         Getnumber - prompts user for a number
  53.         
  54.         Convertnumber - makes sure the user has entered a
  55.  
  56.                 positive whole number
  57.     
  58.         EvenorOdd - determines if number is even or odd }
  59.  
  60.     Var
  61.         
  62.         userentry: real;
  63.  
  64. {        ^
  65.         |
  66.         |__  Just to confuse the issue, we'll introduce a bit of
  67.              error checking.  In this case, we'll allow the user to
  68.              enter in a real number (i.e. with a fractional
  69.              component) and convert it to an integer. }
  70.  
  71.         number: longint;
  72.  
  73.     { ---------------------------------------------------------- }
  74.  
  75.     Procedure Getnumber (Var userchoice: real);
  76.  
  77. {                ^
  78.                 |
  79.                 |__  Here's where the variable is passed to
  80.                  the procedure.  Because the variable is
  81.                  being altered by the procedure, we prefix
  82.                  the name of the variable with "Var".
  83.  
  84.                  The procedure variable name (local
  85.                  identifier) is different from the global
  86.                  variable name.  This makes it much easier
  87.                  to track a bug.  We know that if anything
  88.                  is wrong with "userchoice", the problem
  89.                  must be in the procedure "Getnumber",
  90.                  whereas if there is anything wrong with
  91.                  "userentry", the bug must be in the main
  92.                  program!
  93.  
  94.                  Looking at the main program below, the
  95.                  value for "userchoice" should enter this
  96.                  procedure with a value of 0.00.  The user
  97.                  will type in a new value, and it is this
  98.                  altered variable which will be passed back
  99.                  to the main program.
  100.  
  101.                  After the variable name comes the
  102.                  variable type, which is "real" }
  103.  
  104.     { Prompts user for a number }
  105.  
  106.     begin
  107.  
  108.     writeln;
  109.  
  110.     write('     Please enter a whole number: ');
  111.  
  112.     readln(userchoice);
  113.  
  114.     end; { Getnumber }
  115.  
  116. {    ^
  117.     |
  118.     |__  The variable "userchoice" exits the procedure and
  119.          is passed back to the main program as "userentry".  The
  120.          main program will probably turn it into a nice little
  121.          teapot warmer. }
  122.  
  123.     { ---------------------------------------------------------- }
  124.  
  125.     Procedure Convertnumber 
  126.  
  127.     (realnumber: real; Var integernumber: longint);
  128.  
  129. {     ^
  130.      |
  131.      |__  I've put the local identifiers and types on the next 
  132.           line from the procedure heading to make the code look
  133.           sexy.  What a concept!
  134.  
  135.           Because we'll be converting the real number, we only need it
  136.           as an input, rather than a variable to change.  Therefore, we
  137.           don't have to put the word "Var" before the variable name. 
  138.           This number will not be changed by the procedure, it will be
  139.           converted!  The variable being changed (integernumber) is
  140.           passed with the prefix "Var" because it will be altered.
  141.  
  142.           Try leaving the "Var" out and running the program.  You
  143.           should find that the number is always equal to 0, because
  144.           that is what we have initialised in the main program (see
  145.           below). }   
  146.  
  147.     { Converts a real number to a positive integer }
  148.  
  149.     begin
  150.  
  151.     integernumber := Abs(Round(realnumber));
  152.  
  153. {             ^
  154.              |
  155.              |__  See Tute10.pas! }
  156.  
  157.     end; { Convertnumber }
  158.  
  159. {    ^
  160.     |
  161.     |__  At the end of this procedure, realnumber is unchanged, but
  162.          "integernumber" is passed back to the main program as 
  163.          "number", having being altered by the "Round" command.  If
  164.          only plastic surgery was as easy as this, we'd all be
  165.          millionaires! }
  166.  
  167.     { ---------------------------------------------------------- }
  168.  
  169.     Procedure EvenorOdd (testnumber: longint);
  170.  
  171.     { Determines if an integer is even or odd }
  172.  
  173.     begin
  174.  
  175.     writeln;
  176.  
  177.     If testnumber mod 2 = 0 then
  178.  
  179. {              ^
  180.               |
  181.               |__  See Tute7.pas! }
  182.  
  183.     writeln('     ',testnumber,' is even!')
  184.  
  185.     else
  186.  
  187.     writeln('     ',testnumber,' is odd!');     
  188.     
  189.     writeln;
  190.  
  191.     end; { EvenorOdd }
  192.  
  193.     { ---------------------------------------------------------- }
  194.     { ---------------------------------------------------------- }
  195.  
  196.     begin { Main Program }
  197.  
  198.     userentry := 0.00;
  199.  
  200.     number := 0;
  201.  
  202. {    ^
  203.     |
  204.     |__  These two lines initialise the global variables.  It ain't
  205.          strictly necessary in this case, but it's a damn fine way to
  206.          start a program and anyone reading your code will probably
  207.          want to shake your hand when they see this.
  208.  
  209.          For big programs it's easier if the variable values are set by
  210.          you at the start so you can track them as they change.  I've
  211.          just set these to zero (0.00 for the "real" variable to
  212.          distinguish it), but you could set them to any value within
  213.          the variable type range. }
  214.  
  215.     Getnumber(userentry);
  216.  
  217. {          ^
  218.           |
  219.           |__  Here the global variable is passed to the
  220.                procedure.  Note that when the procedure receives
  221.                the variable, the variable name is changed from the
  222.                global variable "userentry" to the local identifier
  223.                "userchoice".  This makes it easier to track, and
  224.                also confuses any cat that thinks they might have a
  225.                crack at walking across your keyboard and coding an
  226.                Amiga version of "Chicago"® }
  227.  
  228.      Convertnumber(userentry,number);
  229.  
  230. {              ^
  231.               |
  232.               |__  We're passing two variables here, one which is
  233.                just passed as input (userentry), and the other
  234.                which will be altered by the procedure and then
  235.                passed back as a different value (number).
  236.  
  237.                The variables must be passed in the same order
  238.                that they are received by the procedure.  Try
  239.                swapping them.
  240.  
  241.                The variables must also be of the same type. 
  242.                If "Getnumber" is expecting a real-type
  243.                variable, don't try to send it an integer-type
  244.                variable.  Your compiler should pick up such an
  245.                error. }
  246.  
  247.     EvenorOdd(number);
  248.  
  249.      end. { Main Program }
  250.  
  251.     { ---------------------------------------------------------- }
  252.     
  253. {    Spiritual!  The whole main program consists of three lines, and 
  254.      these just call the procedures and pass the global variables to them.
  255.      What a rort!  Here's the spiffy bit; you can use each of the 
  256.      procedures in other programs!  For instance, now whenever you want to 
  257.      convert a real number to an integer, just copy and paste the procedure
  258.      "Convertnumber" into your program and away you go!  This is the real 
  259.      beauty of procedures.  Once you have determined that they are 
  260.      operating according to your specifications, they are transportable.  
  261.      No name changes are needed, because all the variables are defined 
  262.      by local identifiers within the procedure.  For "Convertnumber", all
  263.      you need to do is to send it a real number and an integer, and it will
  264.      send back the converted integer.
  265.  
  266.      Let's say that we want a program which takes a number and finds out 
  267.      if it is a multiple of three.  We can use "Getnumber" and 
  268.      "Convertnumber" from this program.  All we need to do is to delete the
  269.      procedure "EvenorOdd" and insert another which will perform the 
  270.      necessary calculations (called "Multiple").  Our new "Main Program"
  271.      would look something like this...  
  272.  
  273.     Getnumber(userentry);
  274.     Convertnumber(userentry,number);
  275.     Multiple(number);
  276.  
  277.      Cool!
  278.     
  279. {    
  280.                                   
  281.                                   
  282.                                  
  283.                                  
  284.                                   
  285.                                                
  286.                                               
  287.                                               
  288.                                               
  289.                                               
  290.                                               
  291.              «»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»
  292.              «»                                                  «» 
  293.              «»                Duodenum elk pasta                «» 
  294.              «»                                                  «» 
  295.              «»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«» 
  296.  
  297.  
  298.          43  !¡  43  !¡  43  !¡  43  !¡  43  !¡  43  !¡  43  !¡  43
  299.  
  300.  
  301.                                                                      }
  302.  
  303.  
  304.